"""
请假管理接口
作者：资深Flask讲师
功能：
    1. 员工提交请假申请
    2. 查看请假列表（根据角色显示不同数据）
    3. 审批请假（部门经理/管理员）
    4. 取消请假申请
    5. 请假统计
"""

from flask import Blueprint, request, jsonify
from datetime import datetime, timedelta
from sqlalchemy import func, and_, or_, case, extract
from myflask.tools.bd import db
from myflask.models.leave_request import LeaveRequest
from myflask.models.user import User
from myflask.models.department import Department
from myflask.tools.auth import require_role

leave_blue = Blueprint('leave', __name__, url_prefix='/leave')


@leave_blue.route('/submit', methods=['POST'])
def submit_leave():
    """
    提交请假申请
    权限：所有登录用户
    """
    try:
        data = request.get_json()
        user_info = request.user_info
        
        # 数据验证
        if not all([data.get('leave_type'), data.get('start_date'), data.get('end_date'), data.get('days')]):
            return jsonify({"code": 400, "message": "请填写完整的请假信息"})
        
        # 验证日期
        try:
            start_date = datetime.strptime(data['start_date'], '%Y-%m-%d').date()
            end_date = datetime.strptime(data['end_date'], '%Y-%m-%d').date()
        except ValueError:
            return jsonify({"code": 400, "message": "日期格式错误，应为 YYYY-MM-DD"})
        
        if end_date < start_date:
            return jsonify({"code": 400, "message": "结束日期不能早于开始日期"})
        
        # 验证请假天数
        days = float(data['days'])
        if days <= 0:
            return jsonify({"code": 400, "message": "请假天数必须大于0"})
        
        # 获取用户信息
        user = User.query.get(user_info['user_id'])
        if not user:
            return jsonify({"code": 404, "message": "用户不存在"})
        
        # 创建请假申请
        leave_request = LeaveRequest(
            user_id=user_info['user_id'],
            department_id=user.department_id,
            leave_type=data['leave_type'],
            start_date=start_date,
            end_date=end_date,
            days=days,
            reason=data.get('reason', ''),
            status='pending'
        )
        
        db.session.add(leave_request)
        db.session.commit()
        
        return jsonify({
            "code": 200,
            "message": "请假申请提交成功，等待审批",
            "data": leave_request.to_dict()
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({"code": 500, "message": f"提交失败: {str(e)}"})


@leave_blue.route('/list', methods=['GET'])
def leave_list():
    """
    获取请假列表
    权限：
        - 普通员工：只能看自己的请假记录
        - 部门经理：可以看本部门所有请假记录
        - 超级管理员：可以看所有请假记录
    """
    try:
        user_info = request.user_info
        role = user_info.get('role')
        user_id = user_info.get('user_id')
        
        # 获取查询参数
        status = request.args.get('status')  # pending/approved/rejected/cancelled
        page = request.args.get('page', 1, type=int)
        size = request.args.get('size', 20, type=int)
        
        # 构建查询
        query = LeaveRequest.query
        
        # 根据角色过滤数据
        if role == 'employee':
            # 普通员工只能看自己的
            query = query.filter(LeaveRequest.user_id == user_id)
        elif role == 'manager':
            # 部门经理看本部门的
            user = User.query.get(user_id)
            if user and user.department_id:
                query = query.filter(LeaveRequest.department_id == user.department_id)
            else:
                query = query.filter(LeaveRequest.user_id == user_id)
        # admin 不过滤，可以看所有
        
        # 状态过滤
        if status:
            query = query.filter(LeaveRequest.status == status)
        
        # 排序：待审批优先，然后按创建时间倒序
        query = query.order_by(
            case((LeaveRequest.status == 'pending', 0), else_=1),
            LeaveRequest.created_at.desc()
        )
        
        # 分页
        pagination = query.paginate(page=page, per_page=size, error_out=False)
        
        return jsonify({
            "code": 200,
            "message": "获取成功",
            "data": {
                "leave_requests": [leave.to_dict() for leave in pagination.items],
                "pagination": {
                    "total": pagination.total,
                    "page": page,
                    "size": size,
                    "pages": pagination.pages
                }
            }
        })
        
    except Exception as e:
        return jsonify({"code": 500, "message": f"查询失败: {str(e)}"})


@leave_blue.route('/detail/<int:leave_id>', methods=['GET'])
def leave_detail(leave_id):
    """
    获取请假详情
    权限：本人、本部门经理、管理员
    """
    try:
        leave_request = LeaveRequest.query.get(leave_id)
        if not leave_request:
            return jsonify({"code": 404, "message": "请假记录不存在"})
        
        user_info = request.user_info
        role = user_info.get('role')
        user_id = user_info.get('user_id')
        
        # 权限检查
        if role == 'employee' and leave_request.user_id != user_id:
            return jsonify({"code": 403, "message": "无权查看此请假记录"})
        
        if role == 'manager':
            user = User.query.get(user_id)
            if user.department_id != leave_request.department_id:
                return jsonify({"code": 403, "message": "无权查看其他部门的请假记录"})
        
        return jsonify({
            "code": 200,
            "message": "获取成功",
            "data": leave_request.to_dict()
        })
        
    except Exception as e:
        return jsonify({"code": 500, "message": f"查询失败: {str(e)}"})


@leave_blue.route('/approve/<int:leave_id>', methods=['POST'])
@require_role('admin', 'manager')
def approve_leave(leave_id):
    """
    审批请假申请
    权限：部门经理（本部门）、超级管理员
    """
    try:
        data = request.get_json()
        user_info = request.user_info
        
        # 验证参数
        action = data.get('action')  # approve/reject
        if action not in ['approve', 'reject']:
            return jsonify({"code": 400, "message": "操作类型错误，应为 approve 或 reject"})
        
        # 查询请假记录
        leave_request = LeaveRequest.query.get(leave_id)
        if not leave_request:
            return jsonify({"code": 404, "message": "请假记录不存在"})
        
        # 检查状态
        if leave_request.status != 'pending':
            return jsonify({"code": 400, "message": f"该请假申请已{leave_request.status_name}，无法再次审批"})
        
        # 权限检查（部门经理只能审批本部门）
        if user_info['role'] == 'manager':
            user = User.query.get(user_info['user_id'])
            if user.department_id != leave_request.department_id:
                return jsonify({"code": 403, "message": "只能审批本部门的请假申请"})
        
        # 不能审批自己的请假
        if leave_request.user_id == user_info['user_id']:
            return jsonify({"code": 403, "message": "不能审批自己的请假申请"})
        
        # 更新审批状态
        leave_request.status = 'approved' if action == 'approve' else 'rejected'
        leave_request.approver_id = user_info['user_id']
        leave_request.approved_at = datetime.now()
        leave_request.approval_comment = data.get('comment', '')
        
        db.session.commit()
        
        action_name = '通过' if action == 'approve' else '拒绝'
        return jsonify({
            "code": 200,
            "message": f"审批成功，已{action_name}该请假申请",
            "data": leave_request.to_dict()
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({"code": 500, "message": f"审批失败: {str(e)}"})


@leave_blue.route('/cancel/<int:leave_id>', methods=['POST'])
def cancel_leave(leave_id):
    """
    取消请假申请
    权限：申请人本人（仅待审批状态可取消）
    """
    try:
        leave_request = LeaveRequest.query.get(leave_id)
        if not leave_request:
            return jsonify({"code": 404, "message": "请假记录不存在"})
        
        user_info = request.user_info
        
        # 只能取消自己的请假
        if leave_request.user_id != user_info['user_id']:
            return jsonify({"code": 403, "message": "只能取消自己的请假申请"})
        
        # 只有待审批状态才能取消
        if leave_request.status != 'pending':
            return jsonify({"code": 400, "message": f"该请假申请已{leave_request.status_name}，无法取消"})
        
        leave_request.status = 'cancelled'
        db.session.commit()
        
        return jsonify({
            "code": 200,
            "message": "已取消请假申请",
            "data": leave_request.to_dict()
        })
        
    except Exception as e:
        db.session.rollback()
        return jsonify({"code": 500, "message": f"取消失败: {str(e)}"})


@leave_blue.route('/stats/personal', methods=['GET'])
def personal_stats():
    """
    个人请假统计
    权限：本人
    """
    try:
        user_info = request.user_info
        user_id = user_info['user_id']
        
        # 获取年份参数（默认当前年份）
        year = request.args.get('year', datetime.now().year, type=int)
        
        # 统计数据
        stats = db.session.query(
            func.count(LeaveRequest.id).label('total_count'),
            func.sum(LeaveRequest.days).label('total_days'),
            func.sum(case((LeaveRequest.status == 'approved', LeaveRequest.days), else_=0)).label('approved_days'),
            func.sum(case((LeaveRequest.status == 'pending', 1), else_=0)).label('pending_count'),
            func.sum(case((LeaveRequest.status == 'approved', 1), else_=0)).label('approved_count'),
            func.sum(case((LeaveRequest.status == 'rejected', 1), else_=0)).label('rejected_count'),
        ).filter(
            LeaveRequest.user_id == user_id,
            extract('year', LeaveRequest.start_date) == year
        ).first()
        
        # 按类型统计
        type_stats = db.session.query(
            LeaveRequest.leave_type,
            func.count(LeaveRequest.id).label('count'),
            func.sum(LeaveRequest.days).label('total_days')
        ).filter(
            LeaveRequest.user_id == user_id,
            LeaveRequest.status == 'approved',
            extract('year', LeaveRequest.start_date) == year
        ).group_by(LeaveRequest.leave_type).all()
        
        return jsonify({
            "code": 200,
            "message": "获取成功",
            "data": {
                "year": year,
                "total_count": stats.total_count or 0,
                "total_days": float(stats.total_days or 0),
                "approved_days": float(stats.approved_days or 0),
                "pending_count": stats.pending_count or 0,
                "approved_count": stats.approved_count or 0,
                "rejected_count": stats.rejected_count or 0,
                "by_type": [
                    {
                        "leave_type": t.leave_type,
                        "count": t.count,
                        "total_days": float(t.total_days or 0)
                    } for t in type_stats
                ]
            }
        })
        
    except Exception as e:
        return jsonify({"code": 500, "message": f"统计失败: {str(e)}"})


@leave_blue.route('/stats/department', methods=['GET'])
@require_role('admin', 'manager')
def department_stats():
    """
    部门请假统计
    权限：部门经理（本部门）、超级管理员（所有部门）
    """
    try:
        user_info = request.user_info
        department_id = request.args.get('department_id', type=int)
        year = request.args.get('year', datetime.now().year, type=int)
        month = request.args.get('month', type=int)  # 可选月份
        
        # 部门经理只能查看本部门
        if user_info['role'] == 'manager':
            user = User.query.get(user_info['user_id'])
            department_id = user.department_id
        
        if not department_id:
            return jsonify({"code": 400, "message": "请指定部门ID"})
        
        # 构建查询条件
        query = LeaveRequest.query.filter(LeaveRequest.department_id == department_id)
        query = query.filter(extract('year', LeaveRequest.start_date) == year)
        
        if month:
            query = query.filter(extract('month', LeaveRequest.start_date) == month)
        
        # 统计数据
        stats = db.session.query(
            func.count(LeaveRequest.id).label('total_count'),
            func.sum(LeaveRequest.days).label('total_days'),
            func.sum(case((LeaveRequest.status == 'approved', LeaveRequest.days), else_=0)).label('approved_days'),
            func.sum(case((LeaveRequest.status == 'pending', 1), else_=0)).label('pending_count'),
        ).filter(
            LeaveRequest.department_id == department_id,
            extract('year', LeaveRequest.start_date) == year
        ).first()
        
        # 按员工统计
        employee_stats = db.session.query(
            User.id,
            User.real_name,
            User.user,
            func.sum(case((LeaveRequest.status == 'approved', LeaveRequest.days), else_=0)).label('approved_days'),
            func.count(LeaveRequest.id).label('request_count')
        ).join(
            LeaveRequest, User.id == LeaveRequest.user_id
        ).filter(
            LeaveRequest.department_id == department_id,
            extract('year', LeaveRequest.start_date) == year
        ).group_by(User.id).order_by(func.sum(LeaveRequest.days).desc()).limit(10).all()
        
        return jsonify({
            "code": 200,
            "message": "获取成功",
            "data": {
                "department_id": department_id,
                "year": year,
                "month": month,
                "total_count": stats.total_count or 0,
                "total_days": float(stats.total_days or 0),
                "approved_days": float(stats.approved_days or 0),
                "pending_count": stats.pending_count or 0,
                "top_employees": [
                    {
                        "user_id": emp.id,
                        "user_name": emp.real_name or emp.user,
                        "approved_days": float(emp.approved_days or 0),
                        "request_count": emp.request_count
                    } for emp in employee_stats
                ]
            }
        })
        
    except Exception as e:
        return jsonify({"code": 500, "message": f"统计失败: {str(e)}"})

